Categories
Fastify

Server-Side Development with Fastify — Request Validation

Spread the love

Fastify is a small Node framework for developing back end web apps.

In this article, we’ll look at how to create back end apps with Fastify.

Request Validation

We can specify how to validate requests with schema objects.

For example, we can write:

const fastify = require('fastify')({})

const bodyJsonSchema = {
  type: 'object',
  required: ['requiredKey'],
  properties: {
    someKey: { type: 'string' },
    someOtherKey: { type: 'number' },
    requiredKey: {
      type: 'array',
      maxItems: 3,
      items: { type: 'integer' }
    },
    nullableKey: { type: ['number', 'null'] },
    multipleTypesKey: { type: ['boolean', 'number'] },
    multipleRestrictedTypesKey: {
      oneOf: [
        { type: 'string', maxLength: 5 },
        { type: 'number', minimum: 10 }
      ]
    },
    enumKey: {
      type: 'string',
      enum: ['John', 'Foo']
    },
    notTypeKey: {
      not: { type: 'array' }
    }
  }
}

const queryStringJsonSchema = {
  type: 'object',
  properties: {
    name: { type: 'string' },
    excitement: { type: 'integer' }
  }
}

const paramsJsonSchema = {
  type: 'object',
  properties: {
    par1: { type: 'string' },
    par2: { type: 'number' }
  }
}

const headersJsonSchema = {
  type: 'object',
  properties: {
    'x-foo': { type: 'string' }
  },
  required: ['x-foo']
}

const schema = {
  body: bodyJsonSchema,
  querystring: queryStringJsonSchema,
  params: paramsJsonSchema,
  headers: headersJsonSchema
}

fastify.post('/', { schema }, (request, reply)=>{
  reply.send('success')
})

const start = async () => {
  try {
    await fastify.listen(3000, '0.0.0.0')
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}
start()

to add validation schemas for the request body, header, query strings, and URL parameters.

bodyJsonSchema has the schema for the body.

The type property specifies its type.

required specifies which fields are required.

properties specifies the properties that the request body can have.

The type in the properties specifies the type.

queryStringJsonSchema specifies what can be included in the query string.

We specify what can be included in the properties property.

paramsJsonSchema is the object for validating URL parameters.

And headersJsonSchema specifies the schema for the request headers.

We pass all of them into the schema object.

And then we pass that into the 2nd argument of fastify.post to let us validate with them.

Ajv Plugins

We can use the Ajv plugin to validate requests.

For instance, we can write:

const fastify = require('fastify')({
  ajv: {
    plugins: [
      require('ajv-merge-patch')
    ]
  }
})

fastify.post('/', {
  handler (req, reply) { reply.send({ ok: 1 }) },
  schema: {
    body: {
      $patch: {
        source: {
          type: 'object',
          properties: {
            q: {
              type: 'string'
            }
          }
        },
        with: [
          {
            op: 'add',
            path: '/properties/q',
            value: { type: 'number' }
          }
        ]
      }
    }
  }
})

const start = async () => {
  try {
    await fastify.listen(3000, '0.0.0.0')
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}
start()

to add validation with the ajv-merge-patch plugin.

We add the plugin with:

const fastify = require('fastify')({
  ajv: {
    plugins: [
      require('ajv-merge-patch')
    ]
  }
})

Then we add the schema object to add the schema.

The source specifies the request body structure with the data types for the properties.

And the with property lets us add more options for validation.

The op is the operation to do with the existing schema.

'add' lets us add more requirements.

path is the property path of the body to validate.

value.type is the data type we want the properties to be.

Conclusion

We can add request validation with Fastify.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *